package org.shangrila.comm.utils;

import java.io.IOException;
import java.net.URI;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.servlet.http.HttpServletRequest;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;

import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.http.NameValuePair; 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

//import com.sun.net.httpserver.HttpExchange;
//import com.sun.xml.internal.ws.developer.JAXWSProperties;

/**
 * 通过HttpClient4.3.5客户端工具: 调用SoapWs,发出Get/Post请求 
 * @author sophie
 * @date 2018年2月28日 下午2:38:22 
 * @version 1.0
 */
public class WsUtil {
	private static final Logger log = LoggerFactory.getLogger(WsUtil.class);

	static int ConnectTimeout=3000;				//设置连接超时时间，单位毫秒。
	static int ConnectionRequestTimeout=3000;	//设置从connect Manager获取Connection 超时时间，单位毫秒。这个属性是新加的属性，因为目前版本是可以共享连接池的。
	static int SocketTimeout=3000;				//请求获取数据的超时时间，单位毫秒。 如果访问一个接口，多少时间内无法返回数据，就直接放弃此次调用。
	
	/**
	 * 使用 HttpClient 动态调用WS Soap
	 * @param serviceurl
	 * @param requestXml(完整的请求xml，使用SoapUI获取即可)
	 * @param charset
	 * @return
	 */
	public static String sendSoapXml(String serviceurl,String requestXml,String charset) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		
		try {
			RequestConfig requestConfig = RequestConfig.custom()
					.setSocketTimeout(SocketTimeout).setConnectTimeout(ConnectTimeout)
					.setConnectionRequestTimeout(ConnectionRequestTimeout).build();
			httpClient = HttpClients.createDefault();
			HttpPost httpPost = new HttpPost(serviceurl);
			// 设置Timeout
			httpPost.setConfig(requestConfig);
			StringEntity myEntity = new StringEntity(requestXml, charset);
			httpPost.addHeader("Content-Type", "text/xml");
			httpPost.setEntity(myEntity);
			// 执行post请求
			response = httpClient.execute(httpPost);
			// 输出post请求结果
			int status = response.getStatusLine().getStatusCode();// 得到请求结果
			String respInfo = EntityUtils.toString(response.getEntity(),charset);// 得到请求回来的数据
			log.info("WS Executed status: " + status);
			log.info("WS Returned xml: " + respInfo);

			return respInfo;
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if (response != null)
					response.close();
				if (httpClient != null)
					httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * HttpPost(xml/json)请求
	 * @param serviceurl
	 * @param contentType  "application/xml"  "application/json" "text/xml"
	 * @param requestInfo
	 * @param charset
	 * @return
	 */
	public static String sendHttpPost(String serviceurl,String contentType,String requestInfo,String charset) {
		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		
		try {
			RequestConfig requestConfig = RequestConfig.custom()
					.setSocketTimeout(SocketTimeout).setConnectTimeout(ConnectTimeout)
					.setConnectionRequestTimeout(ConnectionRequestTimeout).build();
			httpClient = HttpClients.createDefault();
			HttpPost httpPost = new HttpPost(serviceurl);
			// 设置Timeout
			httpPost.setConfig(requestConfig);
			httpPost.addHeader("Content-Type", contentType);//"application/xml"  "application/json" "text/xml"
			StringEntity myEntity = new StringEntity(requestInfo, charset);
			
			httpPost.setEntity(myEntity);
			// 执行post请求
			response = httpClient.execute(httpPost);
			// 输出post请求结果
			int status = response.getStatusLine().getStatusCode();// 得到请求结果
			String respInfo = EntityUtils.toString(response.getEntity(),charset);// 得到请求回来的数据
			log.info("WS Executed status: " + status);
			log.info("WS Returned string: " + respInfo);

			return respInfo;
		} catch (Exception e) {
			e.printStackTrace();
		}finally {
			try {
				if (response != null)
					response.close();
				if (httpClient != null)
					httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * 发出Post请求(无参数)获取结果
	 * @param uri
	 * @return
	 */
	public static String sendHttpPost(String uri) {

		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(SocketTimeout).setConnectTimeout(ConnectTimeout)
				.setConnectionRequestTimeout(ConnectionRequestTimeout).build();
		HttpPost httpPost = new HttpPost(uri);
		try {
			httpClient = HttpClients.createDefault();
			httpPost.setConfig(requestConfig);
			response = httpClient.execute(httpPost); // /执行请求
			int status = response.getStatusLine().getStatusCode();// 得到请求结果
			log.info("HttpPost status: " + status);//200,300,500
			String respInfo = "";
			respInfo = EntityUtils.toString(response.getEntity(), "UTF-8"); // 得到请求回来的数据
			respInfo = respInfo==null ? null : respInfo.trim();
			log.info("HttpPost Response: " + respInfo);
			return respInfo;
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null)
					response.close();
				if (httpClient != null)
					httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	/**
	 * 发出Post请求(NameValue参数)获取结果
	 * @param uri
	 * @return
	 */
	public static String sendHttpPost(String uri,List<NameValuePair> params) {

		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(SocketTimeout).setConnectTimeout(ConnectTimeout)
				.setConnectionRequestTimeout(ConnectionRequestTimeout).build();
		HttpPost httpPost = new HttpPost(uri);
		try {
			httpClient = HttpClients.createDefault();
			httpPost.setConfig(requestConfig);
	        // 设置参数  
			httpPost.setEntity(new UrlEncodedFormEntity(params));  
			response = httpClient.execute(httpPost); // /执行请求
			int status = response.getStatusLine().getStatusCode();// 得到请求结果
			log.info("HttpPost status: " + status);//200,300,500
			String respInfo = "";
			respInfo = EntityUtils.toString(response.getEntity(), "UTF-8"); // 得到请求回来的数据
			respInfo = respInfo==null ? null : respInfo.trim();
			log.info("HttpPost Response: " + respInfo);
			return respInfo;
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null)
					response.close();
				if (httpClient != null)
					httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	
	/**
	 * 发出get请求(无参数)获取结果
	 * @param uri
	 * @return
	 */
	public static String sendHttpGet(String uri) {

		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(SocketTimeout).setConnectTimeout(ConnectTimeout)
				.setConnectionRequestTimeout(ConnectionRequestTimeout).build();
		HttpGet httpGet = new HttpGet(uri);
		try {
			httpClient = HttpClients.createDefault();
			httpGet.setConfig(requestConfig);
			response = httpClient.execute(httpGet); // /执行请求
			int status = response.getStatusLine().getStatusCode();// 得到请求结果
			log.info("Http Get status: " + status);//200,300,500
			String respInfo = "";
			respInfo = EntityUtils.toString(response.getEntity(), "UTF-8"); // 得到请求回来的数据
			respInfo = respInfo==null ? null : respInfo.trim();
			log.info("Http Get Response: " + respInfo);
			return respInfo;
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null)
					response.close();
				if (httpClient != null)
					httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}
	/**
	 * 发出get请求(NameValue参数)获取结果
	 * @param uri
	 * @return
	 */
	public static String sendHttpGet(String uri,List<NameValuePair> params) {

		CloseableHttpClient httpClient = null;
		CloseableHttpResponse response = null;
		RequestConfig requestConfig = RequestConfig.custom()
				.setSocketTimeout(SocketTimeout).setConnectTimeout(ConnectTimeout)
				.setConnectionRequestTimeout(ConnectionRequestTimeout).build();
		HttpGet httpGet = new HttpGet(uri);
		try {
			httpClient = HttpClients.createDefault();
			httpGet.setConfig(requestConfig);
            // 设置参数  
            httpGet.setURI(new URI(httpGet.getURI().toString() + "?" + EntityUtils.toString(new UrlEncodedFormEntity(params))));  
			response = httpClient.execute(httpGet); // /执行请求
			int status = response.getStatusLine().getStatusCode();// 得到请求结果
			log.info("Http Get status: " + status);//200,300,500
			String respInfo = "";
			respInfo = EntityUtils.toString(response.getEntity(), "UTF-8"); // 得到请求回来的数据
			respInfo = respInfo==null ? null : respInfo.trim();
			log.info("Http Get Response: " + respInfo);
			return respInfo;
			
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				if (response != null)
					response.close();
				if (httpClient != null)
					httpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

    /**
     * 生成元素以及属性的的xml，如果有子元素则在最后插入子元素
     * @param pelement
     * @param pMap
     * @param celement
     * @return
     */
	public static String buildRequestObjectXml(String pelement,Map<String, String> pMap,String celement) {
		StringBuffer soapRequestObject = new StringBuffer();		
		soapRequestObject.append("<" + pelement + ">" );
		Set<String> nameSet = pMap.keySet();
		for (String name : nameSet) {
			soapRequestObject.append("<" + name + ">" + pMap.get(name)	+ "</" + name + ">");
		}
		if(null!=celement)
			soapRequestObject.append(celement);
		soapRequestObject.append("</" + pelement + ">" );				
		
		return soapRequestObject.toString();
	}
	
	/**
	 * 利用StringTokenizer来进行字符串分割
	 */
	public static String[] useStringTokenizer(String str, String sdelimiter) {
		StringTokenizer token = new StringTokenizer(str, sdelimiter);
		String[] array = new String[token.countTokens()];
		int i = 0;
		// System.out.println("count Tokens:"+token.countTokens());
		while (token.hasMoreTokens()) {
			// System.out.println("count cycles:"+i);
			array[i] = token.nextToken();
			i++;
		}
		return array;
	}
	
	/**
	 * 从字符串中获取特定的字符串对应的结果串
	 * @param xmlStr
	 * @param startStr
	 * @param endStr
	 * @return
	 * result = findInString(string,"<RspType>","</RspType>");
	 */
    public static String findInString(String xmlStr,String startStr,String endStr) {  
    	try{
	        int is = xmlStr.indexOf(startStr);
	        int ie = xmlStr.indexOf(endStr,is);    
	        return xmlStr.substring(is+startStr.length(),ie);          
        }catch(Exception ex){
        	//ex.printStackTrace();
        	return "-999"; 
        }    	
    }

	/**
	 * 计算服务时间
	 * @param stime
	 * @return
	 */
	public static long calcEscapeTime(long stime) {
		return System.currentTimeMillis() - stime ;
	}
	
	/**
	 * 获取客户端IP信息
	 * @param wsContext
	 * @return
	 */
	public static String getClientInfo(WebServiceContext wsContext) {
		String clientInfo="ClientInfo ";
		try {
			MessageContext mc = wsContext.getMessageContext();
			/*			
			//JavaAPP发布方式获取客户端IP  public static final java.lang.String HTTP_REQUEST_URL = "com.sun.xml.internal.ws.transport.http.servlet.requestURL";
			HttpExchange exchange = (HttpExchange) mc
					.get(JAXWSProperties.HTTP_EXCHANGE);
			InetSocketAddress isa = exchange.getRemoteAddress();
			clientInfo = clientInfo + "InetSocketAddress: " + isa + "  HostName: "
					+ isa.getAddress().getHostName() + "  Address: "
					+ isa.getAddress().getHostAddress();

			*/
			//web 发布方式获取客户端IP
			HttpServletRequest request = (HttpServletRequest) (mc.get(MessageContext.SERVLET_REQUEST));
			//String clientIP = request.getRemoteAddr();
			//java.util.Map request = (Map) mc.get(MessageContext.HTTP_REQUEST_HEADERS); 			
			//System.out.println("request:"+request);	
			clientInfo = request.getRemoteAddr();
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return clientInfo; 
	}
	
	public static void main(String[] args) {
		String url="http://112.115.0.137:60/GetTestSpeedAddr";
		sendHttpGet(url);
		//wsSoapCallExample();
	}

	public static void wsSoapCallExample() {
		String charset = "UTF-8";
		String wsurl = "http://0.0.0.0:11881/WsIptvUAGService/services";
		String pStart = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\""
				+ " xmlns:uap=\"http://uap.iptv.dfyc.com/\">"
				+ "   <soapenv:Header/>   <soapenv:Body>      <uap:sycIptvAccountPassword>	";
		
		String pEnd = "</uap:sycIptvAccountPassword>   </soapenv:Body> </soapenv:Envelope>";

		String requestXml=pStart+buildRequestXmlExample()+pEnd;
		System.out.println("Request: "+requestXml);
		String retStr = WsUtil.sendSoapXml(wsurl,requestXml, charset);
		System.out.println("Response: "+retStr);
	}
	
	/**
	 * 	动态构造请求参数xml示例
	 * @return
	 */
    public static String buildRequestXmlExample() {   
    	//String reqXmlHeader="<?xml version=\"1.0\" encoding=\"utf-8\"?>";
    	String reqXml="",cxmlStr="",pxmlStr=""; 
    	String celement="Request"; 
    	Map<String, String> pMap = new HashMap<String, String>();
    	Map<String, String> cMap = new HashMap<String, String>();
    	cMap.put("ReqType", "0");
    	cMap.put("ReqCode", "0000");
    	cMap.put("ReqDesc", "0000"); 
    	cxmlStr = WsUtil.buildRequestObjectXml(celement,cMap,null);
    	
    	String pelement="SessionHeader"; 
    	pMap = new HashMap<String, String>();
    	pMap.put("ServiceCode", "CAP10008"); 
    	pMap.put("ActionCode", "0"); 
    	pMap.put("TransactionID", "25UAG201801221415163377293533"); 
    	pMap.put("SrcAreaID", "25"); 
    	pMap.put("DigitalSign", "123"); 
    	pMap.put("ReqTime", "20180122141516"); 
    	
    	pxmlStr = WsUtil.buildRequestObjectXml(pelement,pMap,cxmlStr);
    	reqXml = pxmlStr;
    	
    	celement="ReqInfo"; 
    	cMap = new HashMap<String, String>();
    	cMap.put("Account", "13388855063");
    	cMap.put("Password", "j5n6j0sITCg2eBQHVrmmnQ");
    	cMap.put("AccountType", "2110006"); 
    	cMap.put("PwdType", "05"); 
    	cMap.put("SycType", "1"); 
    	cMap.put("CrmId", "12321"); 
    	cxmlStr = WsUtil.buildRequestObjectXml(celement,cMap,null);
    	
    	pelement="SessionBody"; 
    	pMap = new HashMap<String, String>();
    	pxmlStr = WsUtil.buildRequestObjectXml(pelement,pMap,cxmlStr);
    	reqXml = reqXml + pxmlStr;
    	
    	reqXml ="<CAPRoot>" + reqXml + "</CAPRoot>"; 
    	//pelement="CAPRoot"; 
    	//reqXml = buildRequestObjectXml(pelement,pMap,reqXml);
        return reqXml;
    }
    
}